package com.moli.iov.down.command;

import com.moli.iov.down.command.codec.encode.ProtocolEncoder;
import com.moli.iov.down.command.codec.encode.data.DataEncoder;
import com.moli.iov.down.command.codec.encode.data.RegisterResDataEncoder;
import com.moli.iov.down.command.design.factory.DataEncoderFactory;
import com.moli.iov.down.command.mq.SendCache;
import com.moli.iov.down.command.mq.SendHandle;
import com.moli.iov.down.enums.command.CommandEnum;
import com.moli.iov.down.model.dto.remoting.CommandDto;
import com.moli.iov.exception.BusinessException;
import com.moli.iov.rest.RestResponse;
import com.moli.iov.util.ByteArrayUtil;
import com.moli.iov.util.StringUtil;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Component;

/**
 * <p>
 *  下行命令 处理
 * </p>
 *
 * @author: zql
 * @Date: 2018/12/5 18:15
 */
@Slf4j
@Component("sendCommandService")
public class SendCommandService {

    @Autowired
    private SendCache sendCache;

    @Autowired
    private SendHandle sendHandle;

    @Autowired
    private TaskExecutor taskExecutor;

    /**
     * 下行报文
     * @param commandDtos
     * @return
     */
    public RestResponse sendCommand(List<CommandDto> commandDtos){
        try{
            taskExecutor.execute(() -> {
                log.info("[下行报文] 线程池中执行任务开始");
                for(CommandDto commandDto : commandDtos){
                    this.sendCommand(commandDto);
                }
            });
        }catch(Exception e){
            log.error("下行报文 异常", e);
            return RestResponse.failure("发送命令失败");
        }
        return RestResponse.success();
    }


    /**
     * 下行报文
     * @param commandDto
     * @return
     */
    public RestResponse sendCommand(CommandDto commandDto) {
        try{
            log.info("[下行报文] [{}下发] 0x{} 入参：{}",
                    CommandEnum.getMsg(commandDto.getCommand()),
                    StringUtil.bytesToHexString(commandDto.getCommand()),
                    commandDto);

            DataEncoder dataEncoder =
                    DataEncoderFactory.getDataEncoder(commandDto.getCommand());

            return sendCommand(commandDto, dataEncoder.encode(commandDto));

        }catch(BusinessException e){
            log.error("[下行报文] 失败，未实现协议 0x{} 原因：",
                    StringUtil.bytesToHexString(commandDto.getCommand()),
                    e.getMessage());
            return RestResponse.failure("未实现协议");
        }catch(Exception e){
            log.info("[下行报文] 异常", e);
            return RestResponse.failure("发送命令失败");
        }

    }

    /**
     * 下行报文
     * @param commandDto
     * @param data
     * @return
     */
    public RestResponse sendCommand(CommandDto commandDto, byte[] data){

        ProtocolEncoder protocolEncoder =
                new ProtocolEncoder(commandDto.getCommand(), ByteArrayUtil.strToAscii(commandDto.getVin()), data);
        byte[] allData = protocolEncoder.endcode();

        sendHandle.send(commandDto, allData);

        return RestResponse.success();
    }


    /**
     * 应答发送
     * @return
     */
    public RestResponse sendResponse(CommandDto commandDto) {
        try{
            log.info("[应答发送] 入参  vin：{}  responseTag: {}  serialNumber: {}",
                    commandDto.getVin(), commandDto.getResponseTag(), commandDto.getCommandNo());

            ProtocolEncoder protocolEncoder = new ProtocolEncoder(commandDto.getCommand(),
                    ByteArrayUtil.strToAscii(commandDto.getVin()), new RegisterResDataEncoder().encode(commandDto));

            byte[] responseTags = {commandDto.getResponseTag()};
            protocolEncoder.setResponseTag(responseTags);

            byte[] allData = protocolEncoder.endcode();

            sendHandle.sendResponse(commandDto.getVin(), allData);
            return RestResponse.success();
        }catch(Exception e){
            log.error(String.format("[应答发送] 异常 vin：%s vin:%s", commandDto.getVin(),
                    StringUtil.bytesToHexString(commandDto.getCommand())), e);
            return RestResponse.failure("发送异常");
        }
    }
}
